package com.dxy.app.widget.draw;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.dxy.app.R;
import java.util.concurrent.CountDownLatch;

/**
  *Created by duxingyu on 2017/8/2.14:46
  *Email:
  *Description:浪
  *Principle:波的传递性
  **/
public class WaveView extends View{

  public static final String TAG="TAG_WaveView";
  /**
   * 波浪轨迹
   * */
  private Path path;
  /**
   * 当前画笔
   * */
  private Paint paint;
  /**
   * 当前波浪颜色
   * */
  private int waveColor;
  /**
   * 当前容量，默认为一半
   * */
  private float volume =0.5f;
  /**
   * 当前执行异步处理的线程
   * */
  private Thread thread;
  /**
   * 控件宽高
   * */
  private float width,height;
  /**
   * 当前x,y轴方向上的偏移量
   * */
  private float offsetX,offsetY;
  /**
   * 波浪的振幅
   * */
  private float waveRange =50f;
  /**
   * X轴、Y轴平滑增加的增量
   * */
  private float delX,delY;
  /**
   * 关闭工作线程所需同步工具
   * */
  private CountDownLatch latch =new CountDownLatch(1);
  /**
   * 工作线程开关
   * */
  private volatile boolean isWorkOver =false;
  /**
   * 显示区域的标记点
   * */
  private PointF start,//起始点
      middle,//中间点
      end,//末位点
      upRange,//绘制显示区域第一段贝塞尔曲线起点
      downRange;//绘制显示区域第二段贝塞尔曲线起点
  /**
   * 隐藏区域的标记点
   * */
  private PointF hideStart,//隐藏区域起始点
      hideMiddle,//隐藏区域中间点
      hideEnd,//隐藏区域结束点
      hideUpRange,//绘制隐藏区域第一段赛贝尔曲线起点
      hideDownRange;//绘制隐藏区域第二段赛贝尔曲线起点

  public WaveView(Context context) {
    super(context);
    init(null);
  }

  public WaveView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    TypedArray array =context.obtainStyledAttributes(attrs, R.styleable.WaveView);
    init(array);
  }

  public WaveView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    TypedArray array =context.obtainStyledAttributes(attrs, R.styleable.WaveView);
    init(array);
  }
  /**
   * 初始化参数
   * */
  private void init(TypedArray array){
    if(array!=null){
      waveRange =array.getDimensionPixelSize(R.styleable.WaveView_wave_range,50);
      waveColor =array.getColor(R.styleable.WaveView_wave_color,Color.BLUE);
      array.recycle();
    }else{
      float density =getContext().getResources().getDisplayMetrics().density;
      waveRange =25*density;
      waveColor =Color.BLUE;
    }
    paint =new Paint();
    paint.setAntiAlias(true);
    paint.setColor(waveColor);
    paint.setStyle(Paint.Style.FILL);
    paint.setStrokeCap(Paint.Cap.ROUND);

    path =new Path();
    postDelayed(()->autoWave(),1000);
  }

  /**
   * 第一次初始化各坐标
   * */
  private void initParams(){
    start =new PointF(0,offsetY);
    middle =new PointF(width/2,offsetY);
    end =new PointF(width,offsetY);

    upRange =new PointF(width/4,offsetY+waveRange);
    downRange =new PointF(width*3/4,offsetY-waveRange);

    hideStart =new PointF(-width,offsetY);
    hideMiddle =new PointF(-width/2f,offsetY);
    hideEnd =new PointF(0,offsetY);
    hideUpRange =new PointF(-width*3/4,offsetY+waveRange);
    hideDownRange =new PointF(-width/4,offsetY-waveRange);
  }

  /**
   * 更新当前坐标
   * @param offsetX 每次的增量
   * */
  private void updateOffsetX(float offsetX){
    if(hideStart.y>offsetY){
      /**
       * 增量是2，但是存在当前偏移量处于+2大于基准线，不加小于基准线的情况，所以，此时需要手动将偏移量增减1以达到和基准线一致的情况，否则的话会波浪上下浮动
       * 下同
       * */
      if(hideStart.y-1==offsetY){
        offsetY--;
      }
      delY =-2;
    }else if(hideStart.y<offsetY){
      if(hideStart.y+1==offsetY){
        offsetY++;
      }
      delY =2;
    }else{
      delY =0;
    }

    hideStart.x =hideStart.x+offsetX;
    hideMiddle.x =hideMiddle.x+offsetX;
    hideEnd.x =hideEnd.x+offsetX;
    hideUpRange.x =hideUpRange.x+offsetX;
    hideDownRange.x =hideDownRange.x+offsetX;

    start.x =start.x+offsetX;
    middle.x =middle.x+offsetX;
    end.x =end.x+offsetX;
    upRange.x =upRange.x+offsetX;
    downRange.x =downRange.x+offsetX;

    if(delY!=0){
      hideStart.y =hideStart.y+delY;
      hideMiddle.y =hideMiddle.y+delY;
      hideEnd.y =hideEnd.y+delY;
      hideUpRange.y =hideUpRange.y+delY;
      hideDownRange.y =hideDownRange.y+delY;
      start.y =start.y+delY;
      middle.y =middle.y+delY;
      end.y =end.y+delY;
      upRange.y =upRange.y+delY;
      downRange.y =downRange.y+delY;
    }
  }
  /**
   * 重置当前的坐标
   * */
  private void resetLocX(){
    hideStart.x =-width;
    hideMiddle.x =-width/2f;
    hideEnd.x =0;
    hideUpRange.x =-width*3/4;
    hideDownRange.x =-width/4;

    start.x =0;
    middle.x =width/2;
    end.x =width;

    upRange.x =width/4;
    downRange.x =width*3/4;
  }

  @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    this.width =w;
    this.height =h;
    offsetY =height*volume;
    delX =width/600f;
    initParams();
  }

  @Override protected void onDraw(Canvas canvas) {
    path.reset();
    path.moveTo(hideStart.x,hideStart.y);

    path.quadTo(hideUpRange.x,hideUpRange.y,hideMiddle.x,hideMiddle.y);
    path.quadTo(hideDownRange.x,hideDownRange.y,hideEnd.x,hideEnd.y);

    path.quadTo(upRange.x,upRange.y,middle.x,middle.y);
    path.quadTo(downRange.x,downRange.y,end.x,end.y);
    path.lineTo(end.x,height);
    path.lineTo(hideStart.x,height);
    path.lineTo(hideStart.x,hideStart.y);

    canvas.drawPath(path,paint);
  }
  /**
   * 设置当前进度，用于下载或者显示剩余量
   * @param percent 当前进度(0-1之间的浮点数)
   * */
  public void setCurPercent(float percent){
    if(percent>1||percent<0){
      throw new RuntimeException("percent can not more than one or less than zero!!!");
    }
    this.volume =1-percent;
    offsetY =height*volume;
    /**
     * 传入的volume值因为是浮点数，所以计算出来的offsetY值可能在小数点后还有有效位，此时会导致判断无法归零，所以此处结果已经收敛到(0-1)时，要强转进行归零
     * 否则的话会因为小数点后的有效位导致数值无法归零，绘制效果有上下跳动的显示异常，晃眼睛。
     * */
    offsetY =(int)offsetY;
    Log.i(TAG, "setCurPercent: "+"set new offsetY: current volume:"+volume+",current offsetY:"+offsetY);
  }
  /**
   * 自己浪
   * */
  private void autoWave(){
    thread =new Thread(()->{
      try{
        while(!isWorkOver){
          offsetX+=delX;
          if(offsetX>=width){
            offsetX=0;
            resetLocX();
          }
          updateOffsetX(delX);
          postInvalidate();
          try {
            Thread.sleep(5);
          } catch (InterruptedException e) {
            e.printStackTrace();
            break;
          }
        }
      }finally {
        latch.countDown();
      }
      /*synchronized (WaveView.this){
        notifyAll();
      }*/
    });
    thread.setPriority(4);//设置当前进度的优先级要高于绘制的优先级，所以要将绘制图像的优先级降低一丢丢
    thread.start();
  }

  /**
   * 在关闭界面的时候要先结束浪线程
   * */
  @Override protected synchronized void onDetachedFromWindow() {
    /*thread.interrupt();
    try {//先关闭子线程后再移除控件
      wait();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }*/
    isWorkOver =true;
    try {
      latch.await();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    thread =null;
    super.onDetachedFromWindow();
  }
}
